/**
 * Copyright (C) 2021 - 2031 O-Cubes Co., Ltd.
 */

/****************************************************************
 *  @file    dev_timer.h
 *  @brief   Designware timer device interface header file
 *  @version v1.0
 *  @date    03. Apr. 2023
 *  @author  liuchao
 ****************************************************************/

#ifndef __DEV_TIMER_H__
#define __DEV_TIMER_H__

#include "dev_common.h"

/**
 * @defgroup	DEVICE_HAL_TIMER_CTRLCMD  TIMER Device Control Commands
 * @ingroup	DEVICE_HAL_TIMER
 * @brief	Definitions for timer control command, used in @ref dev_timer::timer_control "TIMER IO Control"
 * @details	These commands defined here can be used in user code directly.
 * - Parameters Usage
 *   - For passing parameters like integer, just use uint32_t/int32_t to directly pass values
 *   - For passing parameters for a structure, please use pointer to pass values
 *   - For getting some data, please use pointer to store the return data
 * - Common Return Values
 *   - @ref E_OK,	Control device successfully
 *   - @ref E_CLSED,	Device is not opened
 *   - @ref E_OBJ,	Device object is not valid or not exists
 *   - @ref E_PAR,	Parameter is not valid for current control command
 *   - @ref E_SYS,	Control device failed, due to hardware issues such as device is disabled
 *   - @ref E_CTX,	Control device failed, due to different reasons like in transfer state
 *   - @ref E_NOSPT,	Control command is not supported or not valid
 * @{
 */

#define TIMER_CMD_SET_CFG                   DEV_SET_SYSCMD(0)

#define TIMER_CMD_GET_CFG                   DEV_SET_SYSCMD(1)

#define TIMER_CMD_ENA_CH                    DEV_SET_SYSCMD(2)

#define TIMER_CMD_DIS_CH                    DEV_SET_SYSCMD(3)

#define TIMER_CMD_SET_ISR                   DEV_SET_SYSCMD(4)

#define TIMER_CMD_GET_ISR                   DEV_SET_SYSCMD(5)

#define TIMER_CMD_DIS_ISR                   DEV_SET_SYSCMD(6)

#define TIMER_CMD_ENA_ISR                   DEV_SET_SYSCMD(7)

/** @} */

/** TIMER interrupt handler or Interrupt Service Routine(ISR) */
typedef void (*DEV_TIMER_HANDLER) (void *ptr);

/**
 * TIMER Device Work Mode Types Enum
 */
typedef enum dev_timer_mode {
	DEV_TIMER_MODE_CLOSE        = 0,    /*!< mode close */
	DEV_TIMER_MODE_ONESHOT_TMR  = 1,    /*!< mode one-shot timer */
	DEV_TIMER_MODE_PERIODIC_TMR = 2,    /*!< mode periodic timer */
	DEV_TIMER_MODE_PWM          = 3,    /*!< mode pwm */
} DEV_TIMER_MODE, *DEV_TIMER_MODE_PTR;

/**
 * TIMER Device Config Struct
 */
typedef struct dev_timer_cfg {
	DEV_TIMER_MODE mode;                    /*!< work mode*/
	uint32_t count_low;                     /*!< count for timer or pwm period low*/
	uint32_t count_high;                    /*!< count for pwm period high*/
	uint32_t duty_cycle;                    /*!< pwm output duty cycle*/
	uint32_t hz;                            /*!< pwm output freq*/
	DEV_TIMER_HANDLER int_ch_handler;
} DEV_TIMER_CFG, *DEV_TIMER_CFG_PTR;

/**
 * @defgroup	DEVICE_HAL_TIMER_DEVSTRUCT	TIMER Device Interface Definition
 * @ingroup	DEVICE_HAL_TIMER
 * @brief	Contains definitions of timer device interface structure.
 * @details	This structure will be used in user implemented code, which was called
 *     @ref DEVICE_IMPL "Device Driver Implement Layer" for timer to use in implementation code.
 *     Application developer should use the TIMER API provided here to access to TIMER devices.
 *     BSP developer should follow the API definition to implement TIMER device drivers.
 * @{
 */
/**
 * @brief	TIMER information struct definition
 * @details	informations about timer open count, working status,
 *     timer registers and ctrl structure
 */
typedef struct dev_timer_info {
	void *timer_ctrl;
	uint32_t opn_cnt;
	// uint32_t status;
	// uint32_t mode;
} DEV_TIMER_INFO, *DEV_TIMER_INFO_PTR;

/**
 * @brief	TIMER device interface definition
 * @details	Define timer device interface, like timer information structure,
 * 	provide functions to open/close/control timer, send/receive data by timer
 * @note	All this details are implemented by user in user porting code
 */
typedef struct dev_timer {
	DEV_TIMER_INFO timer_info;                                             /*!< TIMER device information */
	int32_t (*timer_open)(void);                                           /*!< Open timer device */
	int32_t (*timer_close)(void);                                          /*!< Close timer device */
	int32_t (*timer_control)(uint32_t cmd, void *param2);                  /*!< Control timer device */
	int32_t (*timer_write)(uint32_t mode, uint32_t freq, uint32_t dc);     /*!< Set the configuration of timer*/
	int32_t (*timer_read)(uint32_t *mode, uint32_t *freq, uint32_t *dc);   /*!< Read the configuration of timer*/
} DEV_TIMER, *DEV_TIMER_PTR;
/**
 * @fn		int32_t (* dev_timer::timer_open) (void)
 * @details	open timer device
 * @retval	E_OK	Open successfully without any issues
 * @retval	E_OPNED	If device was opened before with different parameters,
 *			then just increase the @ref dev_timer_info::opn_cnt "opn_cnt" and return @ref E_OPNED
 * @retval	E_OBJ	Device object is not valid
 * @retval	E_PAR	Parameter is not valid
 * @retval	E_NOSPT	Open settings are not supported
 */

/**
 * @fn		int32_t (* dev_timer::timer_close) (void)
 * @details	close an timer device, just decrease the @ref dev_timer_info::opn_cnt "opn_cnt",
 *      if @ref dev_timer_info::opn_cnt "opn_cnt" equals 0, then close the device
 * @retval	E_OK	Close successfully without any issues(including scenario that device is already closed)
 * @retval	E_OPNED	Device is still opened, the device @ref dev_timer_info::opn_cnt "opn_cnt" decreased by 1
 * @retval	E_OBJ	Device object is not valid
 */

/**
 * @fn		int32_t (* dev_timer::timer_control) (uint32_t ch, uint32_t cmd, void *param2)
 * @details	control an timer device [channel number: ch] by ctrl_cmd, with passed param.
 * @param[in]		ch			channel number of timer to control, must >= 0
 * @param[in]		ctrl_cmd	control command, to change or get some thing related to timer
 * @param[in,out]	param		parameters that maybe argument of the command, or return values of the command
 * @retval	E_OK	Control device successfully
 * @retval	E_CLSED	Device is not opened
 * @retval	E_OBJ	Device object is not valid or not exists
 * @retval	E_PAR	Parameter is not valid for current control command
 * @retval	E_SYS	Control device failed, due to hardware issues, such as device is disabled
 * @retval	E_CTX	Control device failed, due to different reasons like in transfer state
 * @retval	E_NOSPT	Control command is not supported or not valid
 */

/**
 * @fn		int32_t (* dev_timer::timer_write) (uint32_t ch, uint32_t mode, uint32_t freq, uint32_t dc)
 * @details	set the configuration of timer.
 * @param[in]	ch		channel number of timer to write, must >= 0
 * @param[in]	mode	set the mode of timer, must not be NULL
 * @param[in]	freq	set the frequency of timer, must not be NULL
 * @param[in]	dc		set the duty cycle of timer, must not be NULL
 * @retval	E_OK	set device successfully
 * @retval	E_OBJ	Device object is not valid or not exists
 * @retval	E_PAR	Parameter is not valid
 * @retval	E_SYS	Can't receive data from hardware due to hardware issues, such as device is disabled
 */

/**
 * @fn		int32_t (* dev_timer::timer_read) (uint32_t ch, uint32_t *mode, uint32_t *freq, uint32_t *dc)
 * @details	read the configuration of timer.
 * @param[in]	ch		channel number of timer to read, must >= 0
 * @param[out]	mode	pointer to data mode of timer, must not be NULL
 * @param[out]	freq	pointer to data frequency of timer, must not be NULL
 * @param[out]	dc		pointer to data duty cycle of timer, must not be NULL
 * @retval	E_OK	Read device successfully
 * @retval	E_OBJ	Device object is not valid or not exists
 * @retval	E_PAR	Parameter is not valid
 * @retval	E_SYS	Can't receive data from hardware due to hardware issues, such as device is disabled
 */
/** @} */

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief	get an @ref dev_timer "timer device" by timer device id.
 * 	For how to use timer device hal refer to @ref dev_timer "Functions in timer device structure"
 * @param[in]
 * @retval	!NULL	pointer to an @ref dev_timer "timer device structure"
 * @retval	NULL	failed to find the timer device by timer_id
 * @note	need to implemented by user in user code
 */
extern DEV_TIMER_PTR timer_get_dev(int32_t timer_id);

#ifdef __cplusplus
}
#endif

/** @} */
#endif /* __DEV_TIMER_H__ */
